package com.yeyks.controller.financial;

import cn.hutool.json.JSONArray;
import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.google.common.collect.Lists;
import com.yeyks.account.dal.domain.AccountInfo;
import com.yeyks.annotation.AdminAppLog;
import com.yeyks.common.appcommon.dto.account.AppAccountDTO;
import com.yeyks.common.appcommon.dto.account.AppIndexDTO;
import com.yeyks.common.appcommon.dto.finance.AppBankInfoDTO;
import com.yeyks.common.appcommon.dto.finance.AppFinanceStatusDTO;
import com.yeyks.common.appcommon.dto.finance.AppHotelBillDTO;
import com.yeyks.common.appcommon.dto.finance.PayAmountFinanceDTO;
import com.yeyks.common.appcommon.param.QueryStatFeeParam;
import com.yeyks.common.appcommon.param.finance.*;
import com.yeyks.common.appcommon.result.CommonAuthHeader;
import com.yeyks.common.appcommon.result.CommonPage;
import com.yeyks.common.appcommon.result.CommonResult;
import com.yeyks.common.base.Arguments;
import com.yeyks.common.constants.AccountType;
import com.yeyks.common.exception.OftenFiledException;
import com.yeyks.common.exception.ServiceException;
import com.yeyks.common.param.finance.FinanceBindParam;
import com.yeyks.common.param.finance.FinanceOrderUpdateParam;
import com.yeyks.common.param.finance.FinanceWithdrawalParam;
import com.yeyks.common.result.withdrawalorder.HotelWithdrawalOrderResult;
import com.yeyks.common.utils.apputil.bean.MyBeanUtils;
import com.yeyks.common.utils.apputil.type.BankTypeJson;
import com.yeyks.commonReference.append.sms.SmsService;
import com.yeyks.commonReference.service.hotel.HotelAccountOverviewService;
import com.yeyks.commonReference.service.hotel.HotelInfoService;
import com.yeyks.commonReference.service.hotel.HotelWithdrawalOrderService;
import com.yeyks.commonReference.service.order.OrderHeadService;
import com.yeyks.controller.BaseController;
import com.yeyks.hotel.dal.domain.HotelWithdrawalOrder;
import com.yeyks.other.dal.domain.BankInfo;
import com.yeyks.other.service.BankInfoService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.RequiredArgsConstructor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

import javax.servlet.http.HttpServletRequest;
import javax.validation.Valid;
import java.util.List;
import java.util.Map;

/**
 * 财务管理
 *
 * @author: dagny
 * @date: 2019/6/28 0028 13:55
 */
@Api(tags = "AppFinancialController财务管理接口", description = "财务管理相关接口信息[收支账户][财务对账单][财务结算]")
@RestController
@RequestMapping("/admin/financial")
@RequiredArgsConstructor(onConstructor = @__(@Autowired))
public class AppFinanceController extends BaseController {

    private final BankInfoService bankInfoService;

    private final SmsService smsService;

    private final HotelWithdrawalOrderService hotelWithdrawalOrderService;

    private final HotelInfoService hotelInfoService;

    private final OrderHeadService orderHeadService;

    private final HotelAccountOverviewService hotelAccountOverviewService;


    @ApiOperation("获取收支账户信息")
    @PostMapping("/get/income")
    public CommonResult<PayAmountFinanceDTO> getIncomeAccount(@Valid GetIncomeAccountParam getIncomeAccountParam) {

        AppAccountDTO appAccountDTO = validToken(getIncomeAccountParam.getToken(),
                getIncomeAccountParam.getVersion(),
                getIncomeAccountParam.getPlatform());

        return hotelInfoService.getIncomeAccount(getIncomeAccountParam,
                MyBeanUtils.convert(appAccountDTO, AccountInfo.class));
    }

    @ApiOperation("设置账号发送短信")
    @PostMapping("/send/code")
    public CommonResult sendPhoneCode(@Valid SendCodeParam sendCodeParam,
                                      HttpServletRequest request) {


        validToken(sendCodeParam.getToken(), sendCodeParam.getVersion(), sendCodeParam.getPlatform());

        Boolean flag = smsService.sendSmsForIncomeAccount(sendCodeParam.getPhone(), sendCodeParam.getType());
        if (flag) {
            return CommonResult.success(null, "验证码发送成功");
        }
        return CommonResult.failed("发送验证码失败");
    }


    @AdminAppLog("绑定收支账户信息")
    @ApiOperation("绑定收支账户信息【和修改是同一个接口】")
    @PostMapping("/add/income")
    public CommonResult addIncomeAccount(@Valid AddIncomeAccountParam param) {

        AppAccountDTO appAccountDTO = validToken(param.getToken(), param.getVersion(), param.getPlatform());

        if (!smsService.verifySmsForSignup(param.getPhone(), param.getCode())) {
            return CommonResult.failed("验证码输入有误");
        }
        try {
            if (!hotelWithdrawalOrderService.bind(MyBeanUtils.convert(appAccountDTO, AccountInfo.class),
                    MyBeanUtils.convert(param, FinanceBindParam.class))) {
                return CommonResult.failed("绑定银行账户失败");
            }
        } catch (ServiceException e) {
            throw new OftenFiledException(e.getMessage());
        }

        return CommonResult.success(null, "绑定成功");
    }

    @ApiOperation("v1.8获取银行卡列表")
    @PostMapping("/bank/list")
    public CommonResult<List<AppBankInfoDTO>> queryBankList(
            @RequestParam(value = "name", required = false, defaultValue = "") String name){

        AppAccountDTO appAccountDTO = validToken(null,null,null);
        List<AppBankInfoDTO> appBankInfoDTOList = Lists.newArrayList();
        if(null != appAccountDTO){
            List<BankInfo> bankInfoList = bankInfoService.list(new QueryWrapper<BankInfo>()
                    .like(BankInfo.NAME, name));
            if(!CollectionUtils.isEmpty(bankInfoList)){
                appBankInfoDTOList = MyBeanUtils.convertArrayList(bankInfoList, AppBankInfoDTO.class);
            }
        }
        return CommonResult.success(appBankInfoDTOList);
    }

    @ApiOperation("v1.8自动添加银行")
    @PostMapping("/add/bank")
    public CommonResult<Boolean> insertBank(@RequestParam(value = "bankJson", defaultValue = "") String bankJson){
        JSONArray objects = null;
        if(!StringUtils.isEmpty(bankJson)){
            objects= JSONUtil.parseArray(bankJson);
        }else{
            objects= JSONUtil.parseArray(BankTypeJson.BANK_JSON);
        }
        List<BankInfo> bankInfoList = JSONUtil.toList(objects, BankInfo.class);
        boolean b = bankInfoService.saveBatch(bankInfoList);
        return CommonResult.success(b);
    }


    @ApiOperation(value = "酒店提现订单查询,[财务结算的列表]")
    @PostMapping("/list")
    public CommonResult<CommonPage<HotelWithdrawalOrderResult>> list(@Valid QueryWithdrawalOrderParam param) {

        AppAccountDTO appAccountDTO = validToken(param.getToken(), param.getVersion(), param.getPlatform());

        return hotelWithdrawalOrderService.adminAppList(param, MyBeanUtils.convert(appAccountDTO, AccountInfo.class));
    }

    @ApiOperation(value = "获取酒店账户余额", notes = "获取酒店账户余额 data格式 \"data\": {\n" +
            "    \"remain\": 59800\n" +
            "    \"phone\": 18582131913\n" +
            "  }\n" +
            "}")
    @PostMapping("/remain")
    public CommonResult<Map<String, Object>> remain(@Valid CommonAuthHeader commonAuthHeader) {

        AppAccountDTO appAccountDTO = validToken(commonAuthHeader.getToken(),
                commonAuthHeader.getVersion(), commonAuthHeader.getPlatform());
        try {
            Map<String, Object> remain = hotelAccountOverviewService.remain(MyBeanUtils.convert(appAccountDTO, AccountInfo.class));
            return CommonResult.success(remain);
        } catch (ServiceException e) {
            throw new OftenFiledException(e.getMessage());
        }
    }


    @ApiOperation(value = "获取C2b账户余额_v1.6.1", notes = "C2b获取账户余额 data格式 \"data\": {\n" +
            "    \"remain\": 59800\n" +
            "    \"phone\": 18582131913\n" +
            "  }\n" +
            "}")
    @PostMapping("/c2b/remain")
    public CommonResult<Map<String, Object>> c2bRemain(@Valid CommonAuthHeader commonAuthHeader){

        AppAccountDTO appAccountDTO = validToken(commonAuthHeader.getToken(),
                commonAuthHeader.getVersion(), commonAuthHeader.getPlatform());
        List<Integer> typeLists = Lists.newArrayList(2, 3, 4, 5);
        Arguments.isTrue(!typeLists.contains(appAccountDTO.getType()), "您无权调用");

        try {
            Map<String, Object> map = hotelWithdrawalOrderService.c2bRemain(MyBeanUtils.convert(appAccountDTO, AccountInfo.class));
            return CommonResult.success(map);
        }catch (ServiceException e){
            throw new OftenFiledException(e.getMessage());
        }
    }


    @ApiOperation(value = "获取vip分佣账户余额_v1.6.1", notes = "C2b获取账户余额 data格式 \"data\": {\n" +
            "    \"remain\": 59800\n" +
            "    \"phone\": 18582131913\n" +
            "  }\n" +
            "}")
    @PostMapping("/vip/remain")
    public CommonResult<Map<String, Object>> vipRemain(@Valid CommonAuthHeader commonAuthHeader){

        AppAccountDTO appAccountDTO = validToken(commonAuthHeader.getToken(),
                commonAuthHeader.getVersion(), commonAuthHeader.getPlatform());
        List<Integer> typeLists = Lists.newArrayList(10, 11, 12, 5);
        Arguments.isTrue(!typeLists.contains(appAccountDTO.getType()), "您无权调用");

        try {
            Map<String, Object> map = hotelWithdrawalOrderService.vipRemain(MyBeanUtils.convert(appAccountDTO, AccountInfo.class));
            return CommonResult.success(map);
        }catch (ServiceException e){
            throw new OftenFiledException(e.getMessage());
        }

    }

    @AdminAppLog("酒店申请提现")
    @ApiOperation(value = "酒店申请提现", notes = "酒店申请提现")
    @PostMapping("/add/withdrawal")
    public CommonResult<Boolean> add(@Valid AddWithdrawalParam param) {

        AppAccountDTO appAccountDTO = validToken(param.getToken(),
                param.getVersion(), param.getPlatform());

        if (AccountType.HotelManager != appAccountDTO.getType()) {
            return CommonResult.failed("当前账户无权提现");
        }
        try {
            param.setType(HotelWithdrawalOrder.OrderType.ORDER.value());
            if (!hotelWithdrawalOrderService.withdrawal(MyBeanUtils.convert(appAccountDTO, AccountInfo.class),
                    MyBeanUtils.convert(param, FinanceWithdrawalParam.class))) {
                return CommonResult.failed("新增提现订单异常");
            }
            return CommonResult.success(true);
        } catch (ServiceException e) {
            throw new OftenFiledException(e.getMessage());
        }
    }


    @ApiOperation(value = "判断是否可以提现", notes = "可以提现返回true，否则直接提示错误信息")
    @PostMapping("/check")
    public CommonResult<Boolean> check(@Valid QueryCheckWithdrawalParam param) {

        AppAccountDTO appAccountDTO = validToken(param.getToken(),
                param.getVersion(), param.getPlatform());

        //0营业提现, 1床垫分成提现
        Integer type = 0;
        if(null != param.getType()){
            type = param.getType();
        }
        try {
            return CommonResult.success(hotelWithdrawalOrderService.checkWithdrawal(MyBeanUtils.convert(appAccountDTO,
                    AccountInfo.class), type));
        }catch (ServiceException e){
            throw new OftenFiledException(e.getMessage());
        }
    }

    @AdminAppLog("修改提现订单状态")
    @ApiOperation(value = "修改提现订单状态", notes = "修改提现订单状态")
    @PostMapping("/update")
    public CommonResult<Boolean> update(@Valid UpdateWithdrawalParam param) {

        AppAccountDTO appAccountDTO = validToken(param.getToken(),
                param.getVersion(), param.getPlatform());

        //0营业提现, 1床垫分成提现
        Integer type = 0;
        if(null != param.getType()){
            type = param.getType();
        }
        param.setType(type);
        List<Integer> list = Lists.newArrayList(2, 4, 5, 6);
        if (!list.contains(param.getStatus())) {
            return CommonResult.failed("不能修改该状态");
        }
        try {
            return CommonResult.success(hotelWithdrawalOrderService.myUpdate(MyBeanUtils.convert(appAccountDTO, AccountInfo.class),
                    MyBeanUtils.convert(param, FinanceOrderUpdateParam.class)));
        }catch (ServiceException e){
            throw new OftenFiledException(e.getMessage());
        }
    }

    @ApiOperation(value = "得到结算筛选状态列表", notes = "得到结算筛选状态列表的接口")
    @PostMapping("/get/status/list")
    public CommonResult<List<AppFinanceStatusDTO>> getStatusList(@Valid CommonAuthHeader param){

        AppAccountDTO appAccountDTO = validToken(param.getToken(),
                param.getVersion(), param.getPlatform());

        return CommonResult.success(hotelWithdrawalOrderService.getStatusList(MyBeanUtils.convert(appAccountDTO, AccountInfo.class)));
    }


    @ApiOperation(value = "分页查询对账单（总公司财务才能看）", notes = "分页查询对账单列表的接口")
    @PostMapping("/list/bill")
    public CommonResult<CommonPage<AppHotelBillDTO>> queryHotelBill(@Valid QueryHotelBillParam param){

        AppAccountDTO appAccountDTO = validToken(param.getToken(),
                param.getVersion(), param.getPlatform());
        if (AccountType.Administrator != appAccountDTO.getType()) {
            throw new OftenFiledException("你无权操作");
        }

        try {
            return orderHeadService.queryHotelBill(param);
        }catch (ServiceException e){
            throw new OftenFiledException(e.getMessage());
        }
    }

    @ApiOperation(value = "分页查询对账单（酒店）", notes = "分页查询对账单（酒店）的接口")
    @PostMapping("/list/bill/hotel")
    public CommonResult<List<AppIndexDTO>> queryBillByHotelId(@Valid QueryStatFeeParam param){


        AppAccountDTO appAccountDTO = validToken(param.getToken(),
                param.getVersion(), param.getPlatform());
        if (AccountType.HotelManager != appAccountDTO.getType()) {
            throw new OftenFiledException("你无权操作");
        }
        return orderHeadService.queryBillByHotelId(param, MyBeanUtils.convert(appAccountDTO, AccountInfo.class));
    }


}
